<template>
  <text v-for="(text, index) in textArray" :key="index"
    :style="{ backgroundColor: text.isSelected ? 'green' : 'transparent' }" @click="doClick(index)">
    <text v-for="(subText, index) in text.subTexts" :key="index"
      :style="{ color: subText.isMark ? props.markedColor : props.normalColor }">
      {{ subText.content }}
    </text>
  </text>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

interface IProps {
  normalColor: string;
  markedColor: string;
  sentence: ISentence;
  isSupportTouchWord: boolean;
}

interface ISentence {
  mark: IRange[] | IMark;
  content: string;
}

interface IMark {
  begin: string;
  end: string;
}

interface IRange {
  location: number;
  length: number;
}

interface IText {
  isWord: boolean;
  content: string;
  startIndex: number;
  subTexts?: ISubText[];
  isSelected?: boolean;
}

interface ISubText {
  content: string;
  isMark: boolean;
}

const props = withDefaults(defineProps<IProps>(), {
  normalColor: "#7C2D10",
  markedColor: "#FFAF00",
  isSupportTouchWord: false,
});

// sentence: {
// // mark: [
// //   { location: 1, length: 3 },
// //   { location: 7, length: 2 },
// // ],
// // content: "Hello, how ar-e yo'u?",

// // mark: {
// //   begin: "<b>",
// //   end: "</b>",
// // },
// // content: "H<b>ell</b>o, h<b>ow</b> ar<b>-</b>e <b>yo</b>'u?",
// }

const textArray = ref<IText[] | null>(null);

watch(
  () => props.sentence,
  (sentence: ISentence) => {
    const texts: IText[] = [];
    var lastText: IText | null = null;
    var markRanges: IRange[];
    var sentenceContent = sentence.content;

    if (sentence.mark instanceof Array) {
      markRanges = sentence.mark as IRange[];
    } else {
      let mark = sentence.mark as IMark;

      markRanges = [];

      const deleteIndexs = [];
      var content = sentence.content;
      var index = 0;
      var tureIndex = 0;
      while (true) {
        let startIndex = content.indexOf(mark.begin);
        let endIndex = content.indexOf(mark.end);
        if (startIndex < 0 || endIndex < 0) {
          break;
        }

        deleteIndexs.push({ startIndex: startIndex + index, endIndex: startIndex + index + mark.begin.length });
        deleteIndexs.push({ startIndex: endIndex + index, endIndex: endIndex + index + mark.end.length });
        markRanges.push({ location: startIndex + tureIndex, length: endIndex - startIndex - mark.begin.length });
        content = content.substring(endIndex + mark.end.length);
        index += endIndex + mark.end.length;
        tureIndex += endIndex - mark.begin.length;
      }

      const charArr = sentenceContent.split("");
      deleteIndexs.reverse().forEach((item) => {
        charArr.splice(item.startIndex, item.endIndex - item.startIndex);
      });
      sentenceContent = charArr.join("");
    }

    for (var i = 0; i < sentenceContent.length; i++) {
      let letter = sentenceContent[i];
      let isWord = /^[a-zA-Z-']$/.test(letter);
      if (!lastText) {
        lastText = { isWord, content: letter, startIndex: i };
      } else {
        if (lastText.isWord === isWord) {
          lastText.content += letter;
        } else {
          texts.push(lastText);
          lastText = { isWord, content: letter, startIndex: i };
        }
      }
      if (i === sentenceContent.length - 1) {
        texts.push(lastText);
      }
    }

    texts.forEach((text) => {
      let ranges: IRange[] = [];
      for (var i = 0; i < markRanges.length; i++) {
        let range = markRanges[i];
        if (text.startIndex > range.location + range.length) {
          continue;
        }

        if (text.startIndex + text.content.length <= range.location) {
          break;
        }

        if (range.location <= text.startIndex) {
          if (range.location + range.length <= text.startIndex + text.content.length) {
            ranges.push({ location: 0, length: range.location + range.length - text.startIndex });
          } else {
            ranges.push({ location: 0, length: text.content.length });
          }
        } else {
          if (range.location + range.length <= text.startIndex + text.content.length) {
            ranges.push({ location: range.location - text.startIndex, length: range.length });
          } else {
            ranges.push({ location: range.location - text.startIndex, length: text.content.length - (range.location - text.startIndex) });
          }
        }
      }

      if (ranges.length === 0) {
        text.subTexts = [{ content: text.content, isMark: false }];
      } else {
        let subTexts: ISubText[] = [];
        var lastRange = { location: 0, length: 0 };
        ranges.forEach((range, index) => {
          if (lastRange.location + lastRange.length < range.location) {
            subTexts.push({
              content: text.content.substring(lastRange.location + lastRange.length, range.location),
              isMark: false,
            });
          }
          subTexts.push({ content: text.content.substring(range.location, range.location + range.length), isMark: true });

          if (index === ranges.length - 1 && range.location + range.length < text.content.length) {
            subTexts.push({
              content: text.content.substring(range.location + range.length, text.content.length),
              isMark: false,
            });
          }
        });
        text.subTexts = subTexts;
      }
    });

    textArray.value = texts;
  },
  {
    immediate: true,
  }
);

const doClick = (index: number) => {
  if (!props.isSupportTouchWord) {
    return;
  }
  if (!textArray.value![index].isWord) {
    return;
  }
  textArray.value!.forEach((item, idx) => {
    item.isSelected = idx === index;
  });
};
</script>

<style scoped></style>
